﻿using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.TextTemplating.VSHost;

namespace InterfaceWeaver.CustomTool
{
    [Guid("E5F8B1A0-DD55-42E3-9A2C-D60FC5BF06EA")]
    [ComVisible(true)]
    public class InterfaceWeaver : BaseCodeGeneratorWithSite
    {
        public override string GetDefaultExtension()
        {
            return ".weaved.cs";
        }

        /// <summary>
        /// Generates the code.
        /// </summary>
        /// <param name="inputFileName">Name of the input file.</param>
        /// <param name="inputFileContent">Content of the input file.</param>
        /// <returns></returns>
        protected string GenerateTextCode(string inputFileName, string inputFileContent)
        {
            try
            {
                return Weaver.Weave(
                    inputFileContent, 
                    this.GetProjectFromSite()).GenerateSourceCode();
            }
            catch (Exception e)
            {
                return string.Format("{0}\n\nStackTrace:\n{1}", e.Message, e.StackTrace);
            }
        }

        protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
        {
            return Encoding.ASCII.GetBytes(GenerateTextCode(inputFileName, inputFileContent));
        }

        /// <summary>
        /// Gets the project from site.
        /// </summary>
        /// <returns></returns>
        private Project GetProjectFromSite()
        {
            object project;
            var hierarchy = (IVsHierarchy)this.GetService(typeof(IVsHierarchy));
            hierarchy.GetProperty(VSConstants.VSITEMID_ROOT,
                                  (int)__VSHPROPID.VSHPROPID_ExtObject,
                                  out project);
            return project as Project;
        }

        ///// <summary>
        ///// Generates the specified input file path.
        ///// </summary>
        ///// <param name="inputFilePath">The input file path.</param>
        ///// <param name="inputFileContents">The input file contents.</param>
        ///// <param name="defaultNamespace">The default namespace.</param>
        ///// <param name="outputFileContents">The output file contents.</param>
        ///// <param name="output">The output.</param>
        ///// <param name="generateProgress">The generate progress.</param>
        ///// <exception cref="System.ArgumentNullException">inputFileContents</exception>
        //public void Generate(string inputFilePath, string inputFileContents, string defaultNamespace, out IntPtr outputFileContents, out int output, IVsGeneratorProgress generateProgress)
        //{
        //    if (inputFileContents == null)
        //    {
        //        throw new ArgumentNullException("inputFileContents");
        //    }

        //    var codeText = this.GenerateCode(inputFilePath, inputFileContents);
        //    if (codeText == null)
        //    {
        //        outputFileContents = IntPtr.Zero;
        //        output = 0;
        //    }
        //    else
        //    {
        //        var array = Encoding.ASCII.GetBytes(codeText);
        //        output = array.Length;
        //        outputFileContents = Marshal.AllocCoTaskMem(output);
        //        Marshal.Copy(array, 0, outputFileContents, output);
        //    }
        //}

        ///// <summary>
        ///// Generates the specified WSZ input file path.
        ///// </summary>
        ///// <param name="wszInputFilePath">The WSZ input file path.</param>
        ///// <param name="bstrInputFileContents">The BSTR input file contents.</param>
        ///// <param name="wszDefaultNamespace">The WSZ default namespace.</param>
        ///// <param name="rgbOutputFileContents">The RGB output file contents.</param>
        ///// <param name="pcbOutput">The PCB output.</param>
        ///// <param name="pGenerateProgress">The p generate progress.</param>
        ///// <returns></returns>
        //public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
        //{
        //    try
        //    {
        //        IntPtr zero = IntPtr.Zero;
        //        int num = 0;
        //        this.Generate(wszInputFilePath, bstrInputFileContents, wszDefaultNamespace, out zero, out num, pGenerateProgress);
        //        rgbOutputFileContents[0] = zero;
        //        pcbOutput = (uint)num;
        //    }
        //    catch
        //    {
        //        pcbOutput = 0u;
        //        rgbOutputFileContents[0] = IntPtr.Zero;
        //        return -2147467259;
        //    }
        //    return 0;
        //}
    }
}
